package com.joe.codemother.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.joe.codemother.annotation.AuthCheck;
import com.joe.codemother.common.BaseResponse;
import com.joe.codemother.common.DeleteRequest;
import com.joe.codemother.common.DeployRequest;
import com.joe.codemother.common.PageRequest;
import com.joe.codemother.entity.User;
import com.joe.codemother.entity.dto.*;
import com.joe.codemother.entity.enums.UserRoleEnums;
import com.joe.codemother.exception.BusinessException;
import com.joe.codemother.exception.ErrorCode;
import com.joe.codemother.util.ResultUtils;
import com.joe.codemother.util.ThrowUtils;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import com.joe.codemother.entity.App;
import com.joe.codemother.service.AppService;
import com.joe.codemother.service.UserService;
import reactor.core.publisher.Flux;

/**
 * 应用 控制层。
 *
 * @author joe
 */
@RestController
@RequestMapping("/app")
public class AppController {

    @Autowired
    private AppService appService;

    @Autowired
    private UserService userService;

    /**
     * 【用户】创建应用（须填写 initPrompt）
     */
    @PostMapping("/add")
    public BaseResponse<Long> add(@RequestBody AppAddRequest addRequest, HttpServletRequest request) {
        ThrowUtils.throwIf(addRequest == null, ErrorCode.PARAMS_ERROR);
        ThrowUtils.throwIf(addRequest.getInitPrompt() == null || addRequest.getInitPrompt().trim().isEmpty(), ErrorCode.PARAMS_ERROR, "initPrompt is required");
        Long loginUserId = userService.getLoginUser(request).getId();
        App app = new App();
        if(StringUtils.isEmpty(addRequest.getAppName())){
            addRequest.setAppName(addRequest.getInitPrompt().substring(0,Math.min(addRequest.getInitPrompt().length(),10)));
        }
        BeanUtil.copyProperties(addRequest, app);
        app.setUserId(loginUserId);
        boolean result = appService.save(app);
        ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
        return ResultUtils.success(app.getId());
    }

    /**
     * 【用户】根据 id 修改自己的应用（仅支持修改名称）
     */
    @PostMapping("/update")
    public BaseResponse<Boolean> updateMyApp(@RequestBody AppUpdateRequest updateRequest, HttpServletRequest request) {
        if (updateRequest == null || updateRequest.getId() == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Long loginUserId = userService.getLoginUser(request).getId();
        App exist = appService.getById(updateRequest.getId());
        ThrowUtils.throwIf(exist == null, ErrorCode.NOT_FOUND_ERROR);
        ThrowUtils.throwIf(!exist.getUserId().equals(loginUserId), ErrorCode.NO_AUTH_ERROR);
        exist.setAppName(updateRequest.getAppName());
        boolean result = appService.updateById(exist);
        ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
        return ResultUtils.success(true);
    }

    /**
     * 【用户】根据 id 删除自己的应用
     */
    @PostMapping("/delete")
    public BaseResponse<Boolean> deleteMyApp(@RequestBody DeleteRequest deleteRequest, HttpServletRequest request) {
        if (deleteRequest == null || deleteRequest.getId() == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Long loginUserId = userService.getLoginUser(request).getId();
        App exist = appService.getById(deleteRequest.getId());
        ThrowUtils.throwIf(exist == null, ErrorCode.NOT_FOUND_ERROR);
        ThrowUtils.throwIf(!exist.getUserId().equals(loginUserId), ErrorCode.NO_AUTH_ERROR);
        boolean result = appService.removeById(deleteRequest.getId());
        return ResultUtils.success(result);
    }

    /**
     * 【用户】根据 id 查看应用详情（仅限自己的）
     */
    @GetMapping("/get")
    public BaseResponse<App> getMyApp(long id, HttpServletRequest request) {
        ThrowUtils.throwIf(id <= 0, ErrorCode.PARAMS_ERROR);
        Long loginUserId = userService.getLoginUser(request).getId();
        App app = appService.getById(id);
        ThrowUtils.throwIf(app == null, ErrorCode.NOT_FOUND_ERROR);
        ThrowUtils.throwIf(!app.getUserId().equals(loginUserId), ErrorCode.NO_AUTH_ERROR);
        return ResultUtils.success(app);
    }

    /**
     * 【用户】分页查询自己的应用列表（支持根据名称查询，每页最多 20 个）
     */
    @PostMapping("/my/list/page")
    public BaseResponse<Page<App>> listMyApps(@RequestBody AppMyQueryRequest queryRequest, HttpServletRequest request) {
        ThrowUtils.throwIf(queryRequest == null, ErrorCode.PARAMS_ERROR);
        int pageNum = Math.max(queryRequest.getPageNum(), 1);
        int pageSize = Math.min(Math.max(queryRequest.getPageSize(), 1), 20);
        Long loginUserId = userService.getLoginUser(request).getId();
        QueryWrapper wrapper = appService.getMyQueryWrapper(queryRequest, loginUserId);
        Page<App> page = appService.page(Page.of(pageNum, pageSize), wrapper);
        return ResultUtils.success(page);
    }

    /**
     * 【用户】分页查询精选的应用列表（支持根据名称查询，每页最多 20 个）
     */
    @PostMapping("/featured/list/page")
    public BaseResponse<Page<App>> listFeaturedApps(@RequestBody AppFeaturedQueryRequest queryRequest) {
        ThrowUtils.throwIf(queryRequest == null, ErrorCode.PARAMS_ERROR);
        int pageNum = Math.max(queryRequest.getPageNum(), 1);
        int pageSize = Math.min(Math.max(queryRequest.getPageSize(), 1), 20);
        QueryWrapper wrapper = appService.getFeaturedQueryWrapper(queryRequest);
        Page<App> page = appService.page(Page.of(pageNum, pageSize), wrapper);
        return ResultUtils.success(page);
    }

    /**
     * 【管理员】根据 id 删除任意应用
     */
    @PostMapping("/admin/delete")
    @AuthCheck(mustRole = "admin")
    public BaseResponse<Boolean> adminDelete(@RequestBody DeleteRequest deleteRequest) {
        if (deleteRequest == null || deleteRequest.getId() == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        boolean result = appService.removeById(deleteRequest.getId());
        return ResultUtils.success(result);
    }

    /**
     * 【管理员】根据 id 更新任意应用（支持更新应用名称、应用封面、优先级）
     */
    @PostMapping("/admin/update")
    @AuthCheck(mustRole = "admin")
    public BaseResponse<Boolean> adminUpdate(@RequestBody AppAdminUpdateRequest updateRequest) {
        if (updateRequest == null || updateRequest.getId() == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        App app = new App();
        BeanUtil.copyProperties(updateRequest, app);
        boolean result = appService.updateById(app);
        ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
        return ResultUtils.success(true);
    }

    /**
     * 【管理员】分页查询应用列表（支持根据除时间外的任何字段查询，每页数量不限）
     */
    @PostMapping("/admin/list/page")
    @AuthCheck(mustRole = "admin")
    public BaseResponse<Page<App>> adminListByPage(@RequestBody AppAdminQueryRequest queryRequest) {
        ThrowUtils.throwIf(queryRequest == null, ErrorCode.PARAMS_ERROR);
        int pageNum = Math.max(queryRequest.getPageNum(), 1);
        int pageSize = Math.max(queryRequest.getPageSize(), 1);
        QueryWrapper wrapper = appService.getAdminQueryWrapper(queryRequest);
        Page<App> page = appService.page(Page.of(pageNum, pageSize), wrapper);
        return ResultUtils.success(page);
    }

    /**
     * 【管理员】根据 id 查看应用详情
     */
    @GetMapping("/admin/get")
    @AuthCheck(mustRole = "admin")
    public BaseResponse<App> adminGet(long id) {
        ThrowUtils.throwIf(id <= 0, ErrorCode.PARAMS_ERROR);
        App app = appService.getById(id);
        ThrowUtils.throwIf(app == null, ErrorCode.NOT_FOUND_ERROR);
        return ResultUtils.success(app);
    }

    /**
     * 应用聊天生成代码（流式 SSE）
     *
     * @param appId   应用 ID
     * @param message 用户消息
     * @param request 请求对象
     * @return 生成结果流
     */
    @GetMapping(value = "/chat/gen/code", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> chatToGenCode(@RequestParam Long appId,
                                      @RequestParam String message,
                                      HttpServletRequest request) {
        // 参数校验
        ThrowUtils.throwIf(appId == null || appId <= 0, ErrorCode.PARAMS_ERROR, "应用ID无效");
        ThrowUtils.throwIf(StrUtil.isBlank(message), ErrorCode.PARAMS_ERROR, "用户消息不能为空");
        // 获取当前登录用户
        User loginUser = userService.getLoginUser(request);
        // 调用服务生成代码（流式）
        return appService.chatToGenCode(message, appId, loginUser);
    }


    @PostMapping
    public BaseResponse<String> deploy(@RequestBody DeployRequest deployRequest,HttpServletRequest request) {
        ThrowUtils.throwIf(deployRequest == null || deployRequest.getAppId() == null, ErrorCode.PARAMS_ERROR);
        Long appId = deployRequest.getAppId();
        User loginUser = userService.getLoginUser(request);
        String result = appService.deployCode(appId, loginUser);
        return ResultUtils.success(result);
    }

}
